#ifndef __CLIENT_COMMON_TABLE_SERIALIZED_included
#define __CLIENT_COMMON_TABLE_SERIALIZED_included

#include <vector>
#include <rapidjson/document.h>

#include "Table.h"
#include "Record.h"

using namespace std;

namespace Client {
namespace Common {

template<class T>
class CTableSerialized : public CTable {

	vector<RecordRef> mRecords;
	string mSerailizeBuf;

public :

	CTableSerialized() { }
	CTableSerialized(string& s) {
		
		if(s.length() <= 2) return;

		CRecord::JsonDocument doc;
		if(doc.Parse<0>(s.c_str()).HasParseError()) {
			Engine::DebugStream << "CTableSerialized - parse json error : " << doc.GetParseError() << '\n';
			return;
		}

		if(!doc.IsArray()) return;
		for(int i = 0; i < doc.Size(); i++) {
			RecordRef r = RecordRef(new T(doc[i]));
			Add(r);
		}
	}

	virtual ~CTableSerialized() { }

	virtual void Add(RecordRef r) {  
		mRecords.push_back(r);
		mCount++;
	}

	virtual string& ToString() {
		
		CRecord::JsonBuffer ss;
		CRecord::JsonWriter writer(ss);

		writer.StartArray();
		int n = mRecords.size();
		for(int i = 0; i < n; i++) {
			mRecords[i]->WriteJson(writer);
		}
		writer.EndArray();
		
		mSerailizeBuf = ss.GetString();
		return mSerailizeBuf;
	}

	virtual void Close() { };

	virtual boost::shared_array<RecordRef>& NextRecords(int n) { 
		
		int first, last;
		CalcNextRecordsIndex(n, first, last);

		n = last - first + 1;
		boost::shared_array<RecordRef> arr(new RecordRef[n]);

		for(int i = 0; i < n; i++) {
			arr[i] = mRecords[first+i];
		}

		if(n == 0) {
			mCurrentRecords.reset();
		}
		else {
			mCurrentRecords = arr;
		}
		
		CommitRecordsIndex(first, first+n-1);

		return mCurrentRecords;
	}

	static TableRef Create(CTable& t) {
		
		int count = t.GetCount();
		if(count == 0) return TableRef();

		TableRef st(new CTableSerialized<T>());
		boost::shared_array<RecordRef> recs = t.CurrentRecords();
		if(!recs) recs = t.NextRecords(count);
		count = t.GetCurrentRecordsCount();
		for(int i = 0; i < count; i++) st->Add(recs[i]);

		return st;
	}
};

} // Common
} // Client

#endif //__CLIENT_COMMON_TABLE_SERIALIZED_included